home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / bfile2.zip / BFILE.CPP next >
Text File  |  1992-01-03  |  12KB  |  518 lines

  1. /*
  2.  
  3.       bfile.cpp
  4.       Btrieve class for Borland C++
  5.       09/06/91
  6.  
  7.       Douglas J. Reilly
  8.       Access Microsystems Inc.
  9.       404 Midstreams Road
  10.       Brick, New Jersey  08724
  11.       (908) 892-2683
  12.       CompuServe 74040,607
  13.  
  14.       Comments?  Questions?  Suggestions?
  15.       Have a paying C/C++ programming job you need done?
  16.       Give me a call.
  17.  
  18.       Released into the public domain.  Do with it as you see fit, but
  19.       if you do anything really neat with it, let me know...
  20.  
  21. 11/11/91  DR  Lots of little changes to better handle variable length
  22.                  records.
  23. 11/12/91  DR  Add support for just_update parm to put_rec();
  24.  
  25. 01/03/92  DR  Fix bug that cause file with owner to corrupt NULL pointer
  26.                  (Thanks to Brian Levine in Orlando!).  Don't use data
  27.                  element when opening file.
  28. */
  29. #define EOS '\0'
  30.  
  31. #include "stdio.h"
  32. #include "stdlib.h"
  33. #include "mem.h"
  34. #include "string.h"
  35. #include "ctype.h"
  36. #include "bfile.h"    // class description for bfile
  37.  
  38. class bfile;
  39.  
  40. // #define this, link it with the TURBCBTR module and see an example.
  41. //    USAGE: bfile /f:filename.ext /k:key_num
  42. //#define TEST
  43. #ifdef TEST
  44. main(int argc,char *argv[])
  45. {
  46.    char temp[100];
  47.    int  ret;
  48.    int  loop;
  49.    static char file[70]={""};
  50.    int key=-1;
  51.    temp[0]='\0';
  52.  
  53.    memset(temp,'\0',100);
  54.  
  55.    for ( loop=1 ; loop<argc ; loop++ )
  56.    {
  57.       if ( argv[loop][0]=='/' )
  58.       {
  59.          switch ( (toupper(argv[loop][1])) )
  60.          {
  61.             case 'K':
  62.                key=atoi(&argv[loop][3]);
  63.                break;
  64.             case 'F':
  65.                strcpy(file,&argv[loop][3]);
  66.                break;
  67.          }
  68.       }
  69.    }
  70.  
  71.  
  72.    bfile sum(file,4096,"SLUGGO",0);
  73.    sum.set_key_num(key);
  74.  
  75.    printf("\nsum.get_rec(temp,B_GET_LO)=%d data=%30.30s temp=|%s|",
  76.                                            sum.get_rec(temp,B_GET_LO),
  77.                                            sum.get_data(),temp);
  78.    do {
  79.       printf("\nsum.get_rec(temp,B_GET_NEXT)=%d data=%30.30s temp=|%s|",
  80.                                            ret=sum.get_rec(temp,B_GET_NEXT),
  81.                                            sum.get_data(),temp);
  82.    } while ( ret==0 );
  83.    return(0);
  84. }
  85. #endif
  86.  
  87. bfile::bfile(char *name,int len,char *towner,int newmode)
  88. {
  89.    int tlen=0;
  90.    char openowner[128];
  91.  
  92.    key_num=0;
  93.    opened=0;
  94.    data=0;
  95.    strcpy(fname,name);
  96.    mode=newmode;
  97.    if ( towner!=0 )
  98.    {
  99.       tlen=(strlen(towner))+1;
  100.       strcpy(openowner,towner);
  101.       strcpy(owner,towner);
  102.    }
  103.    else
  104.    {
  105.       openowner[0]='\0';
  106.       tlen=len;
  107.    }
  108.    status=BTRV(B_OPEN,pos_blk,openowner,&tlen,fname,mode);
  109.    if ( status && status!=BERR_REC_BUF_ERR )
  110.    {
  111. //      printf("\nOpen failed for %s-status %d",fname,status);
  112.    }
  113.    else
  114.    {
  115.       opened=1;
  116.      // DECLARATION!
  117.       struct FIL_SPEC fil_spec;
  118.       get_bstat(&fil_spec);
  119.       file_flag=fil_spec.FILE_FLAG;
  120.       if ( len )
  121.       {
  122.          rec_len=len;
  123.         // get the fixed len from the FIL_SPEC
  124.          fixed_len=fil_spec.REC_LEN;
  125.       }
  126.       else
  127.       {
  128.          if ( variable_len() )  // variable len?
  129.          {
  130.             rec_len=5000;             // assume 5000, what the heck...
  131.          }
  132.          else
  133.          {
  134.             rec_len=fil_spec.REC_LEN;
  135.          }
  136.          fixed_len=fil_spec.REC_LEN;
  137.       }
  138.       last_rec_len=0;
  139.       num_keys=fil_spec.NDX_CNT;
  140.       data=new char[rec_len];
  141.       if ( data==0 )
  142.       {
  143.          close();
  144.          opened=0;
  145.          status=BERR_MEM_ALLOC;
  146.       }
  147.    }
  148. }
  149. bfile::~bfile()
  150. {
  151.    if ( !(opened) )
  152.    {
  153.       return;
  154.    }
  155.    else
  156.    {
  157.       status=BTRV(B_CLOSE,pos_blk,data,&rec_len,fname,mode);
  158.       delete data;
  159.       data=0;
  160.       opened=0;
  161.    }
  162. }
  163. bfile::newfile(char *name,int len,char *towner,int newmode)
  164. {
  165.    int tlen=0;
  166.  
  167.    key_num=0;
  168.    opened=0;
  169.    data=0;
  170.    strcpy(fname,name);
  171.    mode=newmode;
  172.    if ( towner!=0 )
  173.    {
  174.       strcpy(data,towner);
  175.       strcpy(owner,towner);
  176.       tlen=(strlen(towner))+1;
  177.    }
  178.    else
  179.    {
  180.       tlen=len;
  181.    }
  182.    status=BTRV(B_OPEN,pos_blk,data,&tlen,fname,mode);
  183.    if ( status && status!=BERR_REC_BUF_ERR )
  184.    {
  185. //      printf("\nOpen failed for %s-status %d",fname,status);
  186.    }
  187.    else
  188.    {
  189.       opened=1;
  190.      // DECLARATION!
  191.       struct FIL_SPEC fil_spec;
  192.       get_bstat(&fil_spec);
  193.       file_flag=fil_spec.FILE_FLAG;
  194.       if ( len )
  195.       {
  196.          rec_len=len;
  197.         // get the fixed len from the FIL_SPEC
  198.          fixed_len=fil_spec.REC_LEN;
  199.       }
  200.       else
  201.       {
  202.          if ( file_flag&1 )  // variable len?
  203.          {
  204.             rec_len=5000;             // assume 5000, what the heck...
  205.          }
  206.          else
  207.          {
  208.             rec_len=fil_spec.REC_LEN;
  209.          }
  210.          fixed_len=fil_spec.REC_LEN;
  211.       }
  212.       last_rec_len=0;
  213.       num_keys=fil_spec.NDX_CNT;
  214.       data=new char[rec_len];
  215.       if ( data==0 )
  216.       {
  217.          close();
  218.          opened=0;
  219.          status=BERR_MEM_ALLOC;
  220.       }
  221.    }
  222.    return(status);
  223. }
  224.  
  225. int bfile::close()
  226. {
  227.    if ( data!=0 )
  228.    {
  229.       delete data;
  230.       data=0;
  231.    }
  232.    if ( !(opened) )
  233.    {
  234.       return 0;
  235.    }
  236.    else
  237.    {
  238.       status=BTRV(B_CLOSE,pos_blk,data,&rec_len,fname,mode);
  239.       opened=0;
  240.       return 1;
  241.    }
  242. }
  243.  
  244. int bfile::open(int newmode)
  245. {
  246.    if ( opened )
  247.    {
  248.       return 0;
  249.    }
  250.    if ( newmode!=-99 )
  251.    {
  252.       mode=newmode;
  253.    }
  254.    opened=0;
  255.    data=new char[rec_len];
  256.    if ( data==0 )
  257.    {
  258. //      printf("\nOpen failed for %s-No memory",fname);
  259.       status=BERR_MEM_ALLOC;
  260.    }
  261.    if ( owner!=0 )
  262.    {
  263.       strcpy(data,owner);
  264.    }
  265.    status=BTRV(B_OPEN,pos_blk,data,&rec_len,fname,mode);
  266.    if ( status )
  267.    {
  268.       delete data;
  269.       data=0;
  270.    }
  271.    else
  272.    {
  273.       opened=1;
  274.    }
  275.    return(status);
  276. }
  277.  
  278. int bfile::get_rec(char *keystr,int op)
  279. {
  280.    int tlen;
  281.    if ( !(opened) || data==0 )
  282.    {
  283.       return(BERR_NO_OPEN);    // btrieve status for not opened...
  284.    }
  285.    tlen=rec_len;
  286.    memset(data,EOS,rec_len);
  287.    status=BTRV(op,pos_blk,data,&tlen,keystr,key_num);
  288.    last_rec_len=tlen;
  289.    return(status);
  290. }
  291.  
  292. int bfile::put_rec(char *keystr,int tlen,int just_update)
  293. {
  294.    char *tdata;
  295.    char tkey[128];
  296.    int  stat;
  297.  
  298.    tdata=new char[rec_len];
  299.    memcpy(tdata,data,rec_len);
  300.    memcpy(tkey,keystr,128);
  301.  
  302.   // This is how I save btrieve data.  I understand that there is some
  303.   //   potential for problem with this, since by always re-establishing
  304.   //   positioning, I won't know if someone changed the data since I last
  305.   //   got the rec, but in things I have done, I lock the records first
  306.   //   anyway...
  307.   // 11/12/91  IF just_update==1, then just update data using current pos
  308.  
  309.    stat=BERR_NONE;
  310.    if ( !(just_update) && (stat=get_rec(keystr))!=0 )
  311.    {
  312.       if ( stat!=BERR_REC_NOT_FOUND && stat!=BERR_EOF && stat!=BERR_NONE )
  313.       {
  314.          delete tdata;
  315.          return(stat);
  316.       }
  317.      // new record?
  318.       if ( tlen==0 )
  319.       {
  320.          tlen=rec_len;
  321.       }
  322.       status=BTRV(B_INSERT,pos_blk,tdata,&tlen,tkey,key_num);
  323.       last_rec_len=tlen;
  324.    }
  325.    else
  326.    {
  327.       if ( tlen==0 )
  328.       {
  329.          tlen=rec_len;
  330.       }
  331.       status=BTRV(B_UPDATE,pos_blk,tdata,&tlen,tkey,key_num);
  332.       last_rec_len=tlen;
  333.    }
  334.    if ( !(status) )
  335.    {
  336.       memcpy(data,tdata,rec_len);
  337.       strcpy(keystr,tkey);
  338.    }
  339.    delete tdata;
  340.    return status;
  341. }
  342.  
  343. int bfile::del_rec(char *tkeystr)
  344. {
  345.    char *tdata;
  346.    char tkey[128];
  347.    char keystr[256];
  348.    int  stat;
  349.  
  350.    strcpy(keystr,tkeystr);
  351.   // use tdata so as not to destroy infor in data...
  352.    tdata=new char[rec_len];
  353.    memcpy(tdata,data,rec_len);
  354.    memcpy(tkey,keystr,128);
  355.    if ( tkeystr!=0 && (stat=get_rec(keystr))!=0 )
  356.    {
  357.       delete tdata;
  358.       return(stat);
  359.    }
  360.    else
  361.    {
  362.       status=BTRV(B_DELETE,pos_blk,tdata,&rec_len,tkey,key_num);
  363.    }
  364.    if ( !(status) )
  365.    {
  366.       memcpy(data,tdata,rec_len);
  367.       strcpy(keystr,tkey);
  368.    }
  369.    delete tdata;
  370.    return status;
  371. }
  372.  
  373. void bfile::get_bstat(struct FIL_SPEC *fil_spec)
  374. {
  375.    memset((char *)fil_spec,EOS,(sizeof(struct FIL_SPEC)));
  376.    int tlen=(sizeof(struct FIL_SPEC));
  377.    char temp[60];  // S/B big enough to hold extension file name if
  378.                    //   name is returned.
  379.    status=BTRV(B_STAT,pos_blk,(char *)fil_spec,&tlen,temp,mode);
  380.    if ( status==22 )
  381.    {
  382.       status=0;
  383.    }
  384. }
  385. int  bfile::set_pos(char *buf,char *keystr)
  386.    {
  387.       int tlen=rec_len;
  388.       char temp[256];
  389.       memcpy(data,buf,4);
  390.       status=BTRV(B_GET_DIRECT,pos_blk,data,&tlen,temp,key_num);
  391.       if ( keystr )
  392.       {
  393.          strcpy(keystr,temp);
  394.       }
  395.       return(status);
  396.    }
  397.  
  398. int bfile::clone_file(char *destfname,int overwrite)
  399. {
  400.    struct FIL_SPEC fil_spec;
  401.    int tlen=(sizeof(struct FIL_SPEC));
  402.    char new_pos[128];
  403.    int newstat;
  404.    int tkey;
  405.  
  406.    if ( overwrite )
  407.    {
  408.       tkey=0;
  409.    }
  410.    else
  411.    {
  412.       tkey=-1;
  413.    }
  414.    get_bstat(&fil_spec);
  415.    if ( !(get_status()) )
  416.    {
  417.       newstat=BTRV(B_CREATE,new_pos,(char *)&fil_spec,&tlen,destfname,tkey);
  418.    }
  419.    else
  420.    {
  421.       newstat=get_status();
  422.    }
  423.    return(newstat);
  424. }
  425.  
  426. int  bfile::get_key_len(int tkey_num)
  427. {
  428.    struct FIL_SPEC fil_spec;
  429.    int key_loop;
  430.    int key_len=0;
  431.    if ( tkey_num==-1 )
  432.    {
  433.       tkey_num=key_num;
  434.    }
  435.    get_bstat(&fil_spec);
  436.    int loop;
  437.    for ( loop=0,key_loop=0 ; key_loop<tkey_num && loop<24 ; loop++ )
  438.    {
  439.       if ( !(fil_spec.KEY_BUF[loop].KEY_FLAG&16) ) // last seg?
  440.       {
  441.          key_loop++;
  442.       }
  443.    }
  444.    while ( loop<24 &&
  445.            (fil_spec.KEY_BUF[loop].KEY_FLAG&16) ) // another seg?
  446.    {
  447.       key_len+=fil_spec.KEY_BUF[loop].KEY_LEN;
  448.       loop++;
  449.    }
  450.    key_len+=fil_spec.KEY_BUF[loop].KEY_LEN;
  451.    return(key_len);
  452. }
  453.  
  454. // Insert.  made seperate functions to force insert.
  455. int  bfile::insert(char *keystr,int tlen)
  456. {
  457.    char tkey[128];
  458.  
  459.       if ( keystr!=0 )
  460.       {
  461.          strcpy(tkey,keystr);
  462.       }
  463.       else
  464.       {
  465.          key_from_data(tkey);
  466.       }
  467.       if ( tlen==0 )
  468.       {
  469.          tlen=rec_len;
  470.       }
  471.       status=BTRV(B_INSERT,pos_blk,data,&tlen,tkey,key_num);
  472.       last_rec_len=tlen;
  473.       return status;
  474. }
  475.  
  476. int bfile::key_from_data(char *t)
  477. {
  478.    struct FIL_SPEC fil_spec;
  479.    int key_loop;
  480.    int key_len=0;
  481.    get_bstat(&fil_spec);
  482.    int loop;
  483.    for ( loop=0,key_loop=0 ; key_loop<key_num && loop<24 ; loop++ )
  484.    {
  485.       if ( !(fil_spec.KEY_BUF[loop].KEY_FLAG&16) ) // last seg?
  486.       {
  487.          key_loop++;
  488.       }
  489.    }
  490.    while ( loop<24 &&
  491.            (fil_spec.KEY_BUF[loop].KEY_FLAG&16) ) // another seg?
  492.    {
  493.       key_len+=fil_spec.KEY_BUF[loop].KEY_LEN;
  494.       memcpy(t,&data[fil_spec.KEY_BUF[loop].KEY_POS-1],
  495.                      fil_spec.KEY_BUF[loop].KEY_LEN);
  496.       loop++;
  497.    }
  498.    key_len+=fil_spec.KEY_BUF[loop].KEY_LEN;
  499.    memcpy(t,&data[fil_spec.KEY_BUF[loop].KEY_POS-1],
  500.                   fil_spec.KEY_BUF[loop].KEY_LEN);
  501.    return(key_len);
  502. }
  503. long bfile::num_links(int tkey)
  504. {
  505.    struct FIL_SPEC fil_spec;
  506.    int key_loop;
  507.    get_bstat(&fil_spec);
  508.    int loop;
  509.    for ( loop=0,key_loop=0 ; key_loop<tkey && loop<24 ; loop++ )
  510.    {
  511.       if ( !(fil_spec.KEY_BUF[loop].KEY_FLAG&16) ) // last seg?
  512.       {
  513.          key_loop++;
  514.       }
  515.    }
  516.    return( fil_spec.KEY_BUF[loop].KEY_TOTAL );
  517. }
  518.